package cn.me.alphamq.nameserver.starter;

import cn.me.alphamq.nameserver.cache.Container;
import cn.me.alphamq.nameserver.config.cluster.ChainReplicationProperties;
import cn.me.alphamq.nameserver.config.cluster.ClusterProperties;
import cn.me.alphamq.nameserver.config.cluster.MasterSlaveReplicationProperties;
import cn.me.alphamq.nameserver.enumeration.ReplicationModeEnum;
import cn.me.alphamq.nameserver.enumeration.ReplicationRoleEnum;
import cn.me.alphamq.common.event.EventBus;
import cn.me.alphamq.nameserver.handler.cluster.chain.NodeReplicationClientHandler;
import cn.me.alphamq.nameserver.handler.cluster.chain.NodeReplicationServerHandler;
import cn.me.alphamq.nameserver.handler.cluster.masterslave.MasterReplicationHandler;
import cn.me.alphamq.nameserver.handler.cluster.masterslave.SlaveReplicationHandler;
import cn.me.alphamq.common.util.NettyUtil;

/**
 * 基于 netty 启动集群
 *
 * @author f
 */
public class ClusterStarter {

    /**
     * 针对集群的复制模式选择性地开启不同的 netty 进程
     */
    public static void startNettyProcess() {
        ClusterProperties clusterProperties = Container.getClusterProperties();
        ReplicationModeEnum replicationModeEnum = clusterProperties.getReplicationModeEnum();

        // 单机模式不需要开启用于复制的 netty 进程
        if (ReplicationModeEnum.STANDALONE == replicationModeEnum) {
            return;
        }

        // 开启用于复制的 netty 进程
        if (ReplicationModeEnum.MASTER_SLAVE == replicationModeEnum) {
            startMasterSlaveNettyProcess();
        } else if (ReplicationModeEnum.CHAIN == replicationModeEnum) {
            startChainNettyProcess();
        }
    }

    // 对于链式复制集群模式，针对节点的不同选择性地开启不同的 netty 进程
    private static void startChainNettyProcess() {
        ChainReplicationProperties replicationProperties =
                Container.getClusterProperties().getChainReplicationProperties();
        ReplicationRoleEnum role = replicationProperties.getRole();
        if (ReplicationRoleEnum.NODE == role) {
            NettyUtil.startNettyServer(
                    replicationProperties.getPort(),
                    "node-receive-replication-msg-service",
                    new NodeReplicationServerHandler(new EventBus("node-receive-replication-msg-task"))
            );
            Container.setMultiFunctionalChannel(NettyUtil.startNettyClient(
                    replicationProperties.getNextNode(),
                    "node-send-replication-msg-service",
                    new NodeReplicationClientHandler(new EventBus("node-send-replication-msg-task"))
            ));
        } else if (ReplicationRoleEnum.TAIL == role) {
            NettyUtil.startNettyServer(
                    replicationProperties.getPort(),
                    "node-receive-replication-msg-service",
                    new NodeReplicationServerHandler(new EventBus("node-receive-replication-msg-task"))
            );
        }
    }

    // 对于主从复制集群模式，针对节点的不同选择性地开启不同的 netty 进程
    private static void startMasterSlaveNettyProcess() {
        MasterSlaveReplicationProperties replicationProperties
                = Container.getClusterProperties().getMasterReplicationProperties();
        ReplicationRoleEnum role = replicationProperties.getRole();
        // 开启复制的 netty 进程，只要 启动完 或 连接到 服务端 之后，就会返回
        if (ReplicationRoleEnum.MASTER == role) {
            // 对于主节点，需要开启服务端
            NettyUtil.startNettyServer(
                    replicationProperties.getPort(),
                    "master-replication-service",
                    new MasterReplicationHandler(new EventBus("master-replication-task"))
            );
        } else if (ReplicationRoleEnum.SLAVE == role) {
            // 对于从节点，需要开启客户端，与服务端连接，返回与服务端通信的 channel
            Container.setMultiFunctionalChannel(NettyUtil.startNettyClient(
                    replicationProperties.getMaster(),
                    "slave-replication-service",
                    new SlaveReplicationHandler(new EventBus("slave-replication-task"))
            ));
        }
    }

}
